package chat;

import java.awt.*;
import java.awt.List;
import java.awt.event.*;
import java.util.*;

public class UserDialogAWT extends Frame implements UserDialog
{
    private MyInfo zMyInfo;
    private ActivePeerManager zActivePeerManager = null;
    private PendingPeerManager zPendingPeerManager = null;

    private TextField zChatText;
    private TextField zNameText;
    private TextArea zMessagesTextArea;
    private List zPeersList;
    private Map zPrivateMessagersMap = new HashMap();

    public UserDialogAWT( String pTitle , MyInfo pMyInfo )
    {
        super( pTitle );
        IllegalArgument.ifNull( "Title" , pTitle );
        IllegalArgument.ifNull( "MyInfo" , zMyInfo = pMyInfo );

        setLayout( new BorderLayout() );

        add( "North" , layoutNamePanel() );
        add( "Center" , layoutReceivedMessagesPanel() );
        add( "East" , layoutWhoPanel() );
        add( "South" , layoutChatEntryPanel() );
        pack();
        addWindowListener(
            new WindowAdapter()
            {
                public void windowClosing( WindowEvent e )
                {
                    System.exit( 0 );
                }
            }
        );
        show();
        showWho();
        zChatText.requestFocus();
    }

    public void setActivePeerManager( ActivePeerManager pActivePeerManager )
    {
        if ( pActivePeerManager != null )
            zActivePeerManager = pActivePeerManager;
    }

    public void setPendingPeerManager( PendingPeerManager pPendingPeerManager )
    {
        if ( pPendingPeerManager != null )
            zPendingPeerManager = pPendingPeerManager;
    }

    private Panel layoutChatEntryPanel()
    {
        Panel panel = new Panel();
        panel.setLayout( new BorderLayout() );
        panel.add( "West" , new Label( "Message to Send:" ) );
        panel.add( "Center" , zChatText = new TextField() );
        zChatText.addActionListener(
            new ActionListener()
            {
                public void actionPerformed( ActionEvent e )
                {
                    handleCHAT( e.getActionCommand() );
                    zChatText.setText( "" );
                }
            }
        );
        return panel;
    }

    private Panel layoutReceivedMessagesPanel()
    {
        Panel panel = new Panel();
        panel.setLayout( new BorderLayout() );
        panel.add( "North" , new Label( "Received Messages:" ) );
        panel.add( "Center" , zMessagesTextArea = new TextArea() );
        zMessagesTextArea.setEnabled( true );
        zMessagesTextArea.setEditable( false );
        return panel;
    }

    private Panel layoutWhoPanel()
    {
        Panel panel = new Panel();
        panel.setLayout( new BorderLayout() );
        panel.add( "North" , new Label( "Who's On:" ) );
        panel.add( "Center" , zPeersList = new List( 25 , false ) );
        zPeersList.addActionListener(
            new ActionListener()
            {
                public void actionPerformed( ActionEvent e )
                {
                    String lineRest = e.getActionCommand();
                    int spaceAt = lineRest.indexOf( ' ' );
                    if ( spaceAt != -1 )
                        handlePrivateMessageWindowRequest( lineRest.substring( 0 , spaceAt ) );
                    zChatText.requestFocus();
                }
            }
        );
        return panel;
    }

    private Panel layoutNamePanel()
    {
        Panel panel = new Panel();
        panel.setLayout( new FlowLayout( FlowLayout.LEFT ) );
        panel.add( new Label( "Name:" , Label.RIGHT ) );
        panel.add( zNameText = new TextField( "" , 15 ) );
        zNameText.addActionListener(
            new ActionListener()
            {
                public void actionPerformed( ActionEvent e )
                {
                    handleNAMEchange( e.getActionCommand().trim() );
                    zNameText.setText( "" );
                    showWho();
                    zChatText.requestFocus();
                }
            }
        );
        return panel;
    }

    private void send( String pMessage )
    {
        String current = zMessagesTextArea.getText();
        current += pMessage + "\n";
        zMessagesTextArea.setText( current );
    }

    private void showWho()
    {
        zPeersList.removeAll();
        zPeersList.add( zMyInfo.toString() , 0 );
        PeerInfo[] peers = getPeerInfos();
        for ( int i = 0 ; i < peers.length ; i++ )
            zPeersList.add( peers[ i ].toString() , i + 1 );
    }

    public void showUnrecognized( PeerInfo pPeerInfo , String pBadMessage )
    {
        IllegalArgument.ifNull( "PeerInfo" , pPeerInfo );
        IllegalArgument.ifNull( "BadMessage" , pBadMessage );
        send( "Unrecognized Command from (" + pPeerInfo.getID() + " " + pPeerInfo.getChatName() + "): " + pBadMessage );
    }

    public void showStreamsFailed( PeerInfo pPeerInfo )
    {
        IllegalArgument.ifNull( "PeerInfo" , pPeerInfo );
        send( "Unable to Set up I/O Streams with: " + pPeerInfo.toString() );
    }

    public void showConnectFailed( PeerInfo pPeerInfo )
    {
        IllegalArgument.ifNull( "PeerInfo" , pPeerInfo );
        send( "Unable to Connect to: " + pPeerInfo.toString() );
    }

    public void showConnect( PeerInfo pPeerInfo )
    {
        IllegalArgument.ifNull( "PeerInfo" , pPeerInfo );
        showWho();
    }

    public void showDisconnect( PeerInfo pPeerInfo )
    {
        IllegalArgument.ifNull( "PeerInfo" , pPeerInfo );
        UserDialogPrivateMessageAWT subWindow = getPrivateMessageWindow( pPeerInfo );
        if ( subWindow != null )
        {
            unregisterPrivateMessager( pPeerInfo );
            subWindow.dispose();
        }
        showWho();
    }

    public void showCHAT( PeerInfo pPeerInfo , String pMessage )
    {
        IllegalArgument.ifNull( "PeerInfo" , pPeerInfo );
        IllegalArgument.ifNull( "Message" , pMessage );
        send( pPeerInfo.getID() + " " + pPeerInfo.getChatName() + ": " + pMessage );
    }

    public void showPMSG( PeerInfo pPeerInfo , String pMessage )
    {
        IllegalArgument.ifNull( "PeerInfo" , pPeerInfo );
        IllegalArgument.ifNull( "Message" , pMessage );
        UserDialogPrivateMessageAWT subWindow = getPrivateMessageWindow( pPeerInfo );
        if ( subWindow != null )
            subWindow.send( pPeerInfo.getChatName() + ": " + pMessage );
        else
            send( "Private Message From (" + pPeerInfo.getID() + " " + pPeerInfo.getChatName() + "): " + pMessage );
    }

    public void showNAME( PeerInfo pPeerInfo )
    {
        IllegalArgument.ifNull( "PeerInfo" , pPeerInfo );
        showWho();
    }

    public void showHELO( PeerInfo pPeerInfo )
    {
        IllegalArgument.ifNull( "PeerInfo" , pPeerInfo );
        showWho();
    }

    private UserDialogPrivateMessageAWT getPrivateMessageWindow( PeerInfo pPeerInfo )
    {
        return (UserDialogPrivateMessageAWT) zPrivateMessagersMap.get( pPeerInfo );
    }

    public void unregisterPrivateMessager( PeerInfo pPeerInfo )
    {
        IllegalArgument.ifNull( "PeerInfo" , pPeerInfo );
        zPrivateMessagersMap.remove( pPeerInfo );
    }

    private void openPrivateMessageWindow( ActivePeer other )
    {
        zPrivateMessagersMap.put( other.getPeerInfo() , new UserDialogPrivateMessageAWT( this , zMyInfo , other ) );
    }

    private void handleCHAT( String pLine )
    {
        if ( zActivePeerManager == null )     // builder pattern
            send( "No Peer Manager!" );
        else
        {
            zActivePeerManager.sendToAllCHAT( pLine );
            send( zMyInfo.getChatName() + ": " + pLine );
        }
    }

    private void handleNAMEchange( String newName )
    {
        if ( zActivePeerManager == null )     // builder pattern
            send( "No Peer Manager!" );
        else
        {
            zMyInfo.setChatName( newName );
            zActivePeerManager.sendToAllNAME();
        }
    }

    private PeerInfo[] getPeerInfos()
    {
        return (zActivePeerManager != null) ? zActivePeerManager.getPeerInfos() : new PeerInfo[ 0 ]; // builder pattern
    }

    private void handlePrivateMessageWindowRequest( String id )
    {
        if ( zActivePeerManager == null )     // builder pattern
            send( "No Peer Manager!" );
        else
        {
            ActivePeer other = zActivePeerManager.getPeerListenerByID( id );
            if ( other == null )
                send( "Unrecognized Peer ID: " + id );
            else
                openPrivateMessageWindow( other );
        }
    }
}
